﻿
#include "GnsPolygon2.h"
#include <assert.h>
#include <math.h>

GnsPolygon2::GnsPolygon2()
{
}

GnsPolygon2::~GnsPolygon2()
{
}

// 判断两个浮点数是否相等
bool GnsPolygon2::floatEqual(float f1, float f2, float errorRange)
{
	if (fabs(f1 - f2) < errorRange)
		return true;

	return false;
}

float GnsPolygon2::maxFloat(float x, float y)
{
	return (x > y ?  x : y);
}

float GnsPolygon2::minFloat(float x, float y)
{
	return (x < y ?  x : y);
}


// 初始化，初始化后的 _anchor 就是在左下角的原点
// 若没传入多边形，则认为 _staticRect 矩形是多边形
void GnsPolygon2::init(int  rectWidth, int rectHeight, int transformMode, VERTEX4* pots, int iPotCount)
{
	// 针对 _staticRect
	_staticRect.lb.x = -rectWidth / 2;
	_staticRect.lt.x = -rectWidth / 2;

	_staticRect.rb.x = rectWidth / 2;
	_staticRect.rt.x = rectWidth / 2;
	
	_staticRect.lb.y = -rectHeight / 2;
	_staticRect.rb.y = -rectHeight / 2;

	_staticRect.lt.y = rectHeight / 2;
	_staticRect.rt.y = rectHeight / 2;

	// 两个点
	_bulletPot[0].x = -rectWidth / 2;
	_bulletPot[0].y = 0;
	_bulletPot[1].x = rectWidth / 2;
	_bulletPot[1].y = 0;

	// 针对多边形
	if (pots && iPotCount >= 2)		// 有传入多边形
	{
		for (int i = 0; i < iPotCount; i++)
		{
			_vecStaticPot.push_back(pots[i]) ;		// 多边形的静止的点，即相对于静止的锚点的坐标
		}
	}
	else  // 没传入多边形，则认为 _staticRect 矩形是多边形
	{
		_vecStaticPot.push_back(_staticRect.lb);
		_vecStaticPot.push_back(_staticRect.rb);
		_vecStaticPot.push_back(_staticRect.rt);
		_vecStaticPot.push_back(_staticRect.lt);
	}

	// 让下面的值与静止的值一致
	_anchor = _staticAnchor;

	for (int i = 0; i < (int)_vecStaticPot.size(); i++)
		_vecPot.push_back(_vecStaticPot.at(i));
	_rect = _staticRect;

	_xPrevAnchor = _anchor.x;
	_yPrevAnchor = _anchor.y;
	_prevAngle = 0;
}

void GnsPolygon2::init(int  rectWidth, int rectHeight, const vector<VERTEX4>& pots, int transformMode)
{
	// 针对 _staticRect
	_staticRect.lb.x = -rectWidth / 2;
	_staticRect.lt.x = -rectWidth / 2;

	_staticRect.rb.x = rectWidth / 2;
	_staticRect.rt.x = rectWidth / 2;

	_staticRect.lb.y = -rectHeight / 2;
	_staticRect.rb.y = -rectHeight / 2;

	_staticRect.lt.y = rectHeight / 2;
	_staticRect.rt.y = rectHeight / 2;

	// 两个点
	_bulletPot[0].x = -rectWidth / 2;
	_bulletPot[0].y = 0;
	_bulletPot[1].x = rectWidth / 2;
	_bulletPot[1].y = 0;

	// 针对多边形
	if (pots.size() > 0)		// 有传入多边形
	{
		for (int i = 0; i < (int)pots.size(); i++)
		{
			_vecStaticPot.push_back(pots[i]);		// 多边形的静止的点，即相对于静止的锚点的坐标
		}
	}
	else  // 没传入多边形，则认为 _staticRect 矩形是多边形
	{
		_vecStaticPot.push_back(_staticRect.lb);
		_vecStaticPot.push_back(_staticRect.rb);
		_vecStaticPot.push_back(_staticRect.rt);
		_vecStaticPot.push_back(_staticRect.lt);
	}

	// 让下面的值与静止的值一致
	_anchor = _staticAnchor;

	for (int i = 0; i < (int)_vecStaticPot.size(); i++)
		_vecPot.push_back(_vecStaticPot.at(i));
	_rect = _staticRect;

	_xPrevAnchor = _anchor.x;
	_yPrevAnchor = _anchor.y;
	_prevAngle = 0;
}

// 获得多边形数组 _vecPot 的指针
vector<VERTEX4>& GnsPolygon2::getPots() 
{
	return _vecPot;   // 返回 _vecPot 的地址
}

// 获得 _bulletPot 的两个点坐标
void GnsPolygon2::getBulletPot(float& xStart, float& yStart, float& xEnd, float& yEnd)
{
	xStart = _bulletPot[0].x;
	yStart = _bulletPot[0].y;
	xEnd = _bulletPot[1].x;
	yEnd = _bulletPot[1].y;
}

// 设置锚点的新坐标位置，会自动移动多边形
bool GnsPolygon2::setPosition(float x, float y)
{
	bool bEqualX = floatEqual(x, _xPrevAnchor);  // 判断两个浮点数是否相等
	bool bEqualY = floatEqual(y, _yPrevAnchor);  // 判断两个浮点数是否相等

	if (bEqualX && bEqualY)
		return false;  // x位移与y位移都是相等的，不需要移动

	float xMove = x - _xPrevAnchor;		// x轴的位移差值
	float yMove = y - _yPrevAnchor;		// y轴的位移差值
	
	moveBy(xMove, yMove);   // 多边形移动
	return true;
}

// 设置锚点的新坐标位置，会自动移动多边形
bool GnsPolygon2::setPositionForBezier(float x, float y, float& willRotate)
{
	bool bEqualX = floatEqual(x, _xPrevAnchor);  // 判断两个浮点数是否相等
	bool bEqualY = floatEqual(y, _yPrevAnchor);  // 判断两个浮点数是否相等

	if (bEqualX && bEqualY)
		return false;  // x位移与y位移都是相等的，不需要移动

	float dx = x - _xPrevAnchor;		// x轴的位移差值
	float dy = y - _yPrevAnchor;		// y轴的位移差值

	_curBezierAngle = getAngleTwoPoint(dx, dy);

	willRotate = _curBezierAngle - _PrevBezierAngle;

	_PrevBezierAngle = _curBezierAngle;	// 很重要

	moveBy(dx, dy);   // 多边形移动
	return true;
}

// 获得 POLYGON2_DATA，返回多边形顶点的数量
int GnsPolygon2::getPolygon2Data(POLYGON2_DATA&  polygon2Data)
{
	int iCount = 0;

	for (int i = 0; i < _vecPot.size(); i++)
	{
		if (i > POLYGON2_DATA::MAX_POT_NUM)
		{
			assert(false);   // 越界啦
			return 0;
		}
		VERTEX4& vt =  _vecPot.at(i);
		polygon2Data.pots[i].x = vt.x;
		polygon2Data.pots[i].y = vt.y;

		iCount++;
	}

	polygon2Data.iPotNum = iCount;

	polygon2Data.anchor.x = _anchor.x;
	polygon2Data.anchor.y = _anchor.y;

	return iCount;
}

// 移动
int GnsPolygon2::moveBy(float dx, float dy)
{
	
	int iRes = 0;
	VERTEX4  src;

	Mat44  matTran;   // 移动矩阵

	// 根据移动的距离建立移动矩阵
	Mat44::createTranslation(dx, dy, 0, matTran);

	//--- 对 _anchor 进行变换 -------------------------------------
	src = _anchor;
	iRes = Mat44::vertexMultipyMat(&src, &matTran, &_anchor);
	assert(0 == iRes);

	//--- 对 _vecPot 进行变换 -------------------------------------
	if (_transformMode & mask_vecPot > 0)
	{
		for (int i = 0; i < (int)_vecPot.size(); i++)
		{
			src = _vecPot.at(i);
			iRes = Mat44::vertexMultipyMat(&src, &matTran, &_vecPot[i]);
			assert(0 == iRes);
		}
	}

	//--- 对 _bulletPot  进行变换 -------------------------------------
	if (_transformMode & mask_bulletPot > 0)
	{
		src = _bulletPot[0];
		iRes = Mat44::vertexMultipyMat(&src, &matTran, &_bulletPot[0]);
		assert(0 == iRes);

		src = _bulletPot[1];
		iRes = Mat44::vertexMultipyMat(&src, &matTran, &_bulletPot[1]);
		assert(0 == iRes);
	}

	//--- 对 _rect 进行变换 -------------------------------------
	if (_transformMode & mask_rect > 0)
	{
		src = _rect.lb;
		iRes = Mat44::vertexMultipyMat(&src, &matTran, &_rect.lb);
		assert(0 == iRes);

		src = _rect.rb;
		iRes = Mat44::vertexMultipyMat(&src, &matTran, &_rect.rb);
		assert(0 == iRes);

		src = _rect.rt;
		iRes = Mat44::vertexMultipyMat(&src, &matTran, &_rect.rt);
		assert(0 == iRes);

		src = _rect.lt;
		iRes = Mat44::vertexMultipyMat(&src, &matTran, &_rect.lt);
		assert(0 == iRes);
	}

	// 赋值到上一次
	_xPrevAnchor = _anchor.x;	// x轴上一次的锚点值
	_yPrevAnchor = _anchor.y;	// y轴上一次的锚点值

	return 0;
}

// 设置多边形的旋转角度，会自动旋转多边形
bool GnsPolygon2::setAngle(float  angle)
{
	if (floatEqual(angle, _prevAngle))   // 判断两个浮点数是否相等
		return false;  // 相等，不需要旋转

	float  intervalRotateto = angle - _prevAngle;   // 旋转角度差值

	// 相对顺时针旋转，在上一个角度的基础上顺时针旋转 intervalRotateto 度
	rotationZ_By(intervalRotateto);

	return true;
}

// 根据绕Z轴旋转的角度建立绕Z轴旋转的矩阵
int  GnsPolygon2::rotationZ_By(float angleInterval)
{
	int iRes = 0;
	VERTEX4  src;

	// 矩阵1：先将 _anchor 拉回原点，取 _anchor 的负值
	Mat44  matTranZero;			// 移动矩阵
	Mat44::createTranslation(-_anchor.x,  -_anchor.y, 0, matTranZero);

	// 矩阵2：旋转 angle 度
	Mat44  matRotation;	// 旋转矩阵
	Mat44::createRotationZ(angleInterval, matRotation);

	// 矩阵3：再回到 _anchor 点
	Mat44  matTranToAnchor;			// 移动矩阵
	Mat44::createTranslation(_anchor.x, _anchor.y, 0, matTranToAnchor);

	// 综合矩阵
	Mat44  matTotal;
	Mat44  tmp;
	Mat44::multiplication(&matTranZero, &matRotation, &tmp);
	Mat44::multiplication(&tmp, &matTranToAnchor, &matTotal);

	//--- 对 _anchor 进行变换 -------------------------------------
	src = _anchor;
	iRes = Mat44::vertexMultipyMat(&src, &matTotal, &_anchor);
	assert(0 == iRes);

	//--- 对 _vecPot 进行变换 -------------------------------------
	if (_transformMode & mask_vecPot > 0)
	{
		for (int i = 0; i < (int)_vecPot.size(); i++)
		{
			src = _vecPot.at(i);
			iRes = Mat44::vertexMultipyMat(&src, &matTotal, &_vecPot[i]);
			assert(0 == iRes);
		}
	}

	//--- 对 _bulletPot  进行变换 -------------------------------------
	if (_transformMode & mask_bulletPot > 0)
	{
		src = _bulletPot[0];
		iRes = Mat44::vertexMultipyMat(&src, &matTotal, &_bulletPot[0]);
		assert(0 == iRes);

		src = _bulletPot[1];
		iRes = Mat44::vertexMultipyMat(&src, &matTotal, &_bulletPot[1]);
		assert(0 == iRes);
	}

	//--- 对 _rect 进行变换 -------------------------------------
	if (_transformMode & mask_rect > 0)
	{
		src = _rect.lb;
		iRes = Mat44::vertexMultipyMat(&src, &matTotal, &_rect.lb);
		assert(0 == iRes);

		src = _rect.rb;
		iRes = Mat44::vertexMultipyMat(&src, &matTotal, &_rect.rb);
		assert(0 == iRes);

		src = _rect.rt;
		iRes = Mat44::vertexMultipyMat(&src, &matTotal, &_rect.rt);
		assert(0 == iRes);

		src = _rect.lt;
		iRes = Mat44::vertexMultipyMat(&src, &matTotal, &_rect.lt);
		assert(0 == iRes);
	}

	// 赋值到上一次
	_prevAngle += angleInterval;				// 上一次的角度值

	return 0;
}

bool GnsPolygon2::pointInPolygon(const EASY_POINT& p, const EASY_POINT* ptPolygon, int nCount)
{
	int   nCross = 0;

	for (int i = 0; i< nCount;  i++) 
	{
		EASY_POINT p1= ptPolygon[i];
		EASY_POINT p2= ptPolygon[(i+1) % nCount];

		//?求解?y=p.y    与 p1p2 的交点
		if(p1.y== p2.y) //?p1p2?与?y=p0.y平行
			continue;

		if(p.y<minFloat(p1.y, p2.y))// 交点在p1p2延长线上
			continue;

		if(p.y>= maxFloat(p1.y, p2.y))// 交点在p1p2延长线上
			continue;

		//?求交点的?X?坐标?--------------------------------------------------------------??
		double x= (double)(p.y-p1.y)*(double)(p2.x-p1.x) / (double)(p2.y-p1.y) + p1.x;

		if(x>p.x)
			nCross++;//?只统计单边交点
	}

	// 单边交点为偶数，点在多边形之外
	return(nCross%2==1);

	return false;
}

// 获得两个点的线段与X轴的夹角，即 pNext-->pPrev 的连线，线段是有方向的
float GnsPolygon2::getAngleTwoPoint(VERTEX4 p0, VERTEX4 p1)
{
	float angle = 90;
	float dx = p1.x - p0.x;
	float dy = p1.y - p0.y;
	if (floatEqual(dx, 0.0f))   // dx等于0
	{
		return 90; 
	}
	else
	{
		float fTan = dy / dx;
		float radian = atan(fTan);
		angle = Mat44::radianToAngle(radian);
	}

	angle = -angle;

	return angle;
}

// 根据 dx 和 dy 获得夹角，
float GnsPolygon2::getAngleTwoPoint(float  dx, float dy)
{
	float angle = 90;

	if (floatEqual(dx, 0.0f))   // dx等于0
	{
		return 90;
	}
	else
	{
		float fTan = dy / dx;
		float radian = atan(fTan);
		angle = Mat44::radianToAngle(radian);
	}

	angle = -angle;

	return angle;
}

// 获得变换模式
int GnsPolygon2::getTransformMode()
{
	return _transformMode;
}

void GnsPolygon2::test01()
{
	if (0)  // 验证 e 
	{
		for (int i = 0; i < Mat44::ELEMENT_COUNT; i++)
		{
			_mat.setElement16(i, i + 1);
		}

		for (int i = 0; i < Mat44::ROW_COUNT; i++)
		{
			for (int j = 0; j < Mat44::COL_COUNT; j++)
			{
				float fTmp = 0;
				int iRes = _mat.getElement44(i, j, fTmp);
				int iTmp = 0;
			}
		}
	}

	if (0)  // 验证 pe 
	{
		int iCount = 1;
		for (int i = 0; i < Mat44::ROW_COUNT; i++)
		{
			for (int j = 0; j < Mat44::COL_COUNT; j++)
			{
				_mat.setElement44(i, j, iCount);
				iCount++;
			}
		}

		for (int i = 0; i < Mat44::ELEMENT_COUNT; i++)
		{
			float fTmp = 0.0;
			int iRes = _mat.getElement16(i, fTmp);
			int iTmp = 0;
		}
	}

	if (1)  // 两个矩阵相乘
	{
		Mat44 a;
		Mat44 b;
		Mat44 c;

		float fVal[] = {	1, 1, 1, 1,
									1, 1, 1, 1,
									1, 1, 1, 1,
									1, 1, 1, 1 };

		int iType = 0;
		if (0 == iType)
		{
			a.setAllElement(fVal, 16);
			b.setAllElement(fVal, 16);
		}
		else if (1 == iType)
		{
			Mat44::createTranslation(10, 20, 30, a);
			Mat44::createRotationZ(30, b);
		}

		int iRes = Mat44::multiplication(&a, &b, &c);
		assert(0 == iRes);
	}

	if (0)  // 矩阵乘以顶点
	{
		Mat44 a;
		float fVal[] = {	1, 1, 1, 1,
									1, 1, 1, 1,
									1, 1, 1, 1,
									1, 1, 1, 1 };
		a.setAllElement(fVal, 16);

		VERTEX4 b, c;
		
		b.setValue(1, 1, 1, 1);

		//int iRes = Mat44::matMultipyVertex(&a, &b, &c);
		//assert(0 == iRes);
	}

	if (0)  // 矩阵乘以顶点
	{
		VERTEX4 a, c;
		Mat44 b;
		float fVal[] = { 1, 1, 1, 1,
			1, 1, 1, 1,
			1, 1, 1, 1,
			1, 1, 1, 1 };
		b.setAllElement(fVal, 16);

		a.setValue(1, 1, 1, 1);

		int iRes = Mat44::vertexMultipyMat(&a, &b, &c);
		assert(0 == iRes);
	}

	if (1)
	{

	}
}

void GnsPolygon2::test02()
{

}